


#include"gl_DrawFunction.h"
#include"gl_Graphics.h"






void rect_get_left_top(rect* r)  //
{
   r->left = r->right - r->width;
   r->top = r->bottom - r->height;
}
/// <summary>
/// 根据左上、宽高更新右下的位置。
/// </summary>
void rect_get_right_bottom(rect* r)
{
    r->right = r->left + r->width;
    r->bottom = r->top + r->height;
}
/// <summary>
/// 根据右下、左上的位置更新宽高。
/// </summary>
void rect_get_width_height(rect* r)
{
    r->width = r->right - r->left;
    r->height = r->bottom - r->top;
}




/// <summary>
/// 初始化绘图类。
/// </summary>
/// <param name="g">绘图函数</param>
/// <param name="function_area">绘制函数的区域。x，y轴的刻度区域，</param>
/// <param name="font">刻度的文本样式</param>
/// <param name="xfont">x轴刻度显示样式。0：显示实际数字；1：作为时间戳显示</param>
/// <param name="yfont">y轴刻度显示样式。=0左右两边分别显示y1,y2的刻度；=1左边显示刻度；=-1右边显示刻度。</param>
void TwoFunction_init(TwoFunction*tw, rect function_area, TextFont* font, int xfont,int yfont)
{
    tw->xscaleFont = xfont;
    tw->yscaleFont = yfont;
    tw->left = function_area.left;
    tw->top = function_area.top;
    tw->right = function_area.right;
    tw->bottom = function_area.bottom;
    tw->width = function_area.width;
    tw->height = function_area.height;
    tw->scale_curve_gap = 3;  // 刻度与文本 3像素刻度间隔。

    //现在划分的是整个function_area，绘制xy刻度文本后要重置left,top,right,bottom.使其表示函数绘图区。
    // if (tw->xscaleFont == 0) 
    {
        tw->curveArea.top = tw->top;
        tw->curveArea.bottom = tw->bottom - font->size - tw->scale_curve_gap;
        tw->curveArea.height = tw->height - font->size - tw->scale_curve_gap;

        tw->y1scale_area.left = tw->left;
        tw->y1scale_area.top = tw->top;
        tw->y1scale_area.bottom = tw->bottom - font->size - tw->scale_curve_gap;
        tw->y1scale_area.height = tw->height - font->size - tw->scale_curve_gap;

        tw->y2scale_area.right = tw->right;
        tw->y2scale_area.top = tw->top;
        tw->y2scale_area.bottom = tw->bottom - font->size - tw->scale_curve_gap;
        tw->y2scale_area.height = tw->height - font->size - tw->scale_curve_gap;

        tw->xscale_area.top = tw->bottom - font->size;
        tw->xscale_area.bottom = tw->bottom;
        tw->xscale_area.height = font->size;
    }

    tw->scalefont = *font;

}

/// <summary>
/// 初始化xy数组与points，获取数组点的上下左右边界x_min, x_max, y_min, y_max;
/// </summary>
/// <param name="tw">结构体。</param>
/// <param name="x_1">第一组函数点x坐标</param>
/// <param name="y_1">第一组函数点y坐标</param>
/// <param name="n1">第一组函数点的个数</param>
/// <param name="x_2">第二组函数点x坐标</param>
/// <param name="y_2">第二组函数点y坐标</param>
/// <param name="n2">第二组函数点个数</param>
void TwoFunction_init_func(TwoFunction* tw, float* x_1, float* y_1, int n1, float* x_2, float* y_2, int n2)
{
    if (y_1 != NULL && x_1 != NULL) {
        tw->x1 = x_1;
        tw->y1 = y_1;
        tw->pointsNumber1 = n1;
        tw->x_min_ = x_1[0], tw->x_max_ = x_1[0];
        tw->y1_min_ = y_1[0], tw->y1_max_ = y_1[0];
        for (int i = 0; i < tw->pointsNumber1; i++) {
            tw->x_min_ = tw->x_min_ > tw->x1[i] ? tw->x1[i] : tw->x_min_;
            tw->x_max_ = tw->x_max_ < tw->x1[i] ? tw->x1[i] : tw->x_max_;
            tw->y1_min_ = tw->y1_min_ > tw->y1[i] ? tw->y1[i] : tw->y1_min_;
            tw->y1_max_ = tw->y1_max_ < tw->y1[i] ? tw->y1[i] : tw->y1_max_;
        }
        // y的最大最小值不用缩放，在下面init_yscale函数的运算中会进行缩放。
        tw->y1_min = tw->y1_min_;  //
        tw->y1_max = tw->y1_max_;  //
        if (tw->y1_max == tw->y1_min) {
            tw->y1_max = tw->y1_max + 1;
            tw->y1_min = tw->y1_min - 1;
        }
    }
    else
    {
        tw->x1 = NULL;
        tw->y1 = NULL;
        tw->pointsNumber1 = 0;

        tw->y1_min_ = 0;
        tw->y1_max_ = 0;
        tw->y1_min = tw->y1_min_;  //
        tw->y1_max = tw->y1_max_;
        if (tw->y1_max == tw->y1_min) {
            tw->y1_max = tw->y1_max + 1;
            tw->y1_min = tw->y1_min - 1;
        }
    }

    if (y_2 != NULL && x_2 != NULL) {
        tw->x2 = x_2;
        tw->y2 = y_2;
        tw->pointsNumber2 = n2;
        if (y_1 == NULL) {
            tw->x_min_ = x_2[0], tw->x_max_ = x_2[0];
        }
        tw->y2_min_ = y_2[0], tw->y2_max_ = y_2[0];
        for (int i = 0; i < tw->pointsNumber2; i++) {
            tw->x_min_ = tw->x_min_ > tw->x2[i] ? tw->x2[i] : tw->x_min_;
            tw->x_max_ = tw->x_max_ < tw->x2[i] ? tw->x2[i] : tw->x_max_;
            tw->y2_min_ = tw->y2_min_ > tw->y2[i] ? tw->y2[i] : tw->y2_min_;
            tw->y2_max_ = tw->y2_max_ < tw->y2[i] ? tw->y2[i] : tw->y2_max_;
        }
        // y的最大最小值不用缩放，在下面init_yscale函数的运算中会进行缩放。
        tw->y2_min = tw->y2_min_;  //
        tw->y2_max = tw->y2_max_;
        if (tw->y2_max == tw->y2_min) {
            tw->y2_max = tw->y2_max + 1;
            tw->y2_min = tw->y2_min - 1;
        }
    }
    else
    {
        tw->x2 = NULL;
        tw->y2 = NULL;
        tw->pointsNumber2 = 0;

        tw->y2_min_ = 0;
        tw->y2_max_ = 0;
        tw->y2_min = tw->y2_min_;  //
        tw->y2_max = tw->y2_max_;
        if (tw->y2_max == tw->y2_min) {
            tw->y2_max = tw->y2_max + 1;
            tw->y2_min = tw->y2_min - 1;
        }
    }

    //tw->x_min = tw->x_min_;
    //tw->x_max = tw->x_max_;

    tw->x_min = tw->x_min_ - (tw->x_max_ - tw->x_min_) * 0.05;  //图表可以显示的最小值要比点的最小值要小，这样左边的点就不会与坐标轴重合
    tw->x_max = tw->x_max_ + (tw->x_max_ - tw->x_min_) * 0.05;  //图表可以显示的最大值要比点的最大值要大，这样右边的点就不会与坐标轴重合
    if (tw->x_max == tw->x_min) {
        tw->x_max = tw->x_max + 1;
        tw->x_min = tw->x_min - 1;
    }

}

/// <summary>
/// 初始化xy数组与points，同时设置上下左右边界x_min, x_max, y_min, y_max;
/// </summary>
/// <param name="tw">结构体。</param>
/// <param name="x_1">第一组函数点x坐标</param>
/// <param name="y_1">第一组函数点y坐标</param>
/// <param name="n1">第一组函数点的个数</param>
/// <param name="x_2">第二组函数点x坐标</param>
/// <param name="y_2">第二组函数点y坐标</param>
/// <param name="n2">第二组函数点个数</param>
/// <param name="xmin">x坐标值的最小值</param>
/// <param name="xmax">x坐标值的最大值</param>
/// <param name="y1min">y1坐标值的最小值</param>
/// <param name="y1max">y1坐标值的最大值</param>
/// <param name="y2min">y2坐标值的最小值</param>
/// <param name="y2max">y2坐标值的最大值</param>
void TwoFunction_set_min_max(TwoFunction* tw, float* x_1, float* y_1, int n1, float* x_2, float* y_2, int n2,
    float xmin, float xmax, float y1min, float y1max, float y2min, float y2max)
{
    tw->x_min_ = xmin;
    tw->x_max_ = xmax;
    tw->y1_min_ = y1min;
    tw->y2_min_ = y2min;
    tw->y1_max_ = y1max;
    tw->y2_max_ = y2max;



    tw->x_min_ = tw->x_min_ - (tw->x_max_ - tw->x_min_) * 0.01;  //图表可以显示的最小值要比点的最小值要小，这样左边的点就不会与坐标轴重合
    tw->x_max_ = tw->x_max_ + (tw->x_max_ - tw->x_min_) * 0.01;  //图表可以显示的最大值要比点的最大值要大，这样右边的点就不会与坐标轴重合
    if (tw->x_max_ == tw->x_min_) {
        tw->x_max_ = tw->x_max_ + 1;
        tw->x_min_ = tw->x_min_ - 1;
    }
    if (tw->y1_max_ == tw->y1_min_) {
        tw->y1_max_ = tw->y1_max_ + 1;
        tw->y1_min_ = tw->y1_min_ - 1;
    }
    if (tw->y2_max_ == tw->y2_min_) {
        tw->y2_max_ = tw->y2_max_ + 1;
        tw->y2_min_ = tw->y2_min_ - 1;
    }
    tw->x_max = tw->x_max_;
    tw->x_min = tw->x_min_;
    tw->y1_max = tw->y1_max_;
    tw->y1_min = tw->y1_min_;
    tw->y2_max = tw->y2_max_;
    tw->y2_min = tw->y2_min_;

}

// 设置极值点。
void set_ex()
{

}

/// <summary>
/// 获取函数的x坐标在图片上的x坐标
/// </summary>
/// <param name="fx">函数的x坐标</param>
/// <returns>图片上的x坐标值</returns>
int TwoFunction_get_funcx_in_pic(TwoFunction* tw, float fx)
{
    return (fx - tw->x_min) / (tw->x_max - tw->x_min) * tw->curveArea.width + tw->curveArea.left;
}
/// <summary>
/// 获取函数1的y坐标在图片上的y坐标
/// </summary>
/// <param name="fy">函数的y坐标</param>
/// <returns>图片上的y坐标值</returns>
int TwoFunction_get_funcy1_in_pic(TwoFunction* tw, float fy)
{
    return tw->curveArea.bottom - (fy - tw->y1_min) / (tw->y1_max - tw->y1_min) * tw->curveArea.height;
}
/// <summary>
/// 获取函数2的y坐标在图片上的y坐标
/// </summary>
/// <param name="fy">函数的y坐标</param>
/// <returns>图片上的y坐标值</returns>
int TwoFunction_get_funcy2_in_pic(TwoFunction* tw, float fy)
{
    return tw->curveArea.bottom - (fy - tw->y2_min) / (tw->y2_max - tw->y2_min) * tw->curveArea.height;
}

/// <summary>
/// 在graphics上绘制一个点。
/// </summary>
/// <param name="x">点的x坐标</param>
/// <param name="y">点的y坐标</param>
/// <param name="pointsize">点的尺寸(点的长宽像素点)</param>
/// <param name="pointstyle">点的形状。0 / 1 （空心 / 实心）圆形；2 / 3（空心 / 实心）正方形；4 （空心 ）三角形；</param>
/// <param name="color">点颜色</param>
void TwoFunction_draw_point(int x, int y, int pointsize, int pointstyle, int color)
{
    if (pointsize < 2)
        graphics_draw_point(x, y, color);
    //putpixel(x, y, color);
    else if (pointstyle == 0)
        draw_circle(x, y, pointsize / 2,  color);
    else if (pointstyle == 1)        
        draw_solidcircle(x, y, pointsize / 2,  color);
    else if (pointstyle == 2)
        draw_rectangle(x - pointsize / 2, y - pointsize / 2, pointsize, pointsize, color);
    else if (pointstyle == 3)
        draw_solidrectangle(x - pointsize / 2, y - pointsize / 2, pointsize, pointsize, color);
    else if (pointstyle == 4)
    {
        int px[3];
        int py[3];
        px[0] = x - pointsize / 2;
        py[0] = y + pointsize / 2;
        px[1] = x + pointsize / 2;
        py[1] = y + pointsize / 2;
        px[2] = x;
        py[2] = y - pointsize / 2;
        draw_triangle(px, py, color);
    }

}
    
/// <summary>
/// 绘制函数数组(x1,y1),(x2,y2)的点。
/// </summary>
/// <param name="is_show_y1">是否显示函数y1的点</param>
/// <param name="is_show_y2">是否显示函数y2的点</param>
/// <param name="point_color1">函数y1的点颜色数组。如果有定义颜色数组，则用数组颜色，点的样式是空心圆。否则用默认颜色和样式</param>
/// <param name="point_color2">函数y2的点颜色数组。如果有定义颜色数组，则用数组颜色，点的样式是空心圆。否则用默认颜色和样式</param>
void TwoFunction_draw_points(TwoFunction* tw,bool is_show_y1, bool is_show_y2, COLOR_RGB* point_color1, COLOR_RGB* point_color2)
{
    //tw->pointsize_1 = 9 - (tw->pointsNumber1 / 500);
    //tw->pointsize_2 = 9 - (tw->pointsNumber2 / 500);
    //int minsize = 3;
    //tw->pointsize_1 = tw->pointsize_1 > minsize ? tw->pointsize_1 : minsize;
    //tw->pointsize_2 = tw->pointsize_2 > minsize ? tw->pointsize_2 : minsize;

    int x, y;
    if (is_show_y1)//绘制point1
    {
        if (point_color1 == NULL) {
            COLOR_RGB color = tw->point_color_1;
            for (int i = 0; i < tw->pointsNumber1; i++) {
                x = TwoFunction_get_funcx_in_pic(tw, tw->x1[i]);
                y = TwoFunction_get_funcy1_in_pic(tw, tw->y1[i]);
                TwoFunction_draw_point(x, y, tw->pointsize_1, tw->pointstyle_1, color);
            }
        }
        else
        {
            for (int i = 0; i < tw->pointsNumber1; i++) {
                x = TwoFunction_get_funcx_in_pic(tw, tw->x1[i]);
                y = TwoFunction_get_funcy1_in_pic(tw, tw->y1[i]);
                TwoFunction_draw_point(x, y, tw->pointsize_1, tw->pointstyle_1, point_color1[i]);
            //    _getch();    
            }
        }
    }
    if (is_show_y2)//绘制point2
    {
        if (point_color2 == NULL) {
            COLOR_RGB color = tw->point_color_2;
            for (int i = 0; i < tw->pointsNumber2; i++) {
                x = TwoFunction_get_funcx_in_pic(tw, tw->x2[i]);
                y = TwoFunction_get_funcy2_in_pic(tw, tw->y2[i]);
                TwoFunction_draw_point(x, y, tw->pointsize_2, tw->pointstyle_2, color);
            }
        }
        else
        {
            for (int i = 0; i < tw->pointsNumber2; i++) {
                x = TwoFunction_get_funcx_in_pic(tw, tw->x2[i]);
                y = TwoFunction_get_funcy2_in_pic(tw, tw->y2[i]);
                TwoFunction_draw_point(x, y, tw->pointsize_2, tw->pointstyle_2, point_color2[i]);
            }
        }
    }
}
  
/// <summary>
/// 绘制两条函数
/// </summary>
/// <param name="is_show_y1">是否显示函数 y1</param>
/// <param name="is_show_y2">是否显示函数 y2</param>
void TwoFunction_draw_func(TwoFunction* tw, bool is_show_y1, bool is_show_y2)
{
    if (is_show_y1) {
        for (int i = 0; i < tw->pointsNumber1 - 1; i++)
        {            
            draw_line(TwoFunction_get_funcx_in_pic(tw, tw->x1[i]), TwoFunction_get_funcy1_in_pic(tw, tw->y1[i]),
                TwoFunction_get_funcx_in_pic(tw, tw->x1[i + 1]), TwoFunction_get_funcy1_in_pic(tw, tw->y1[i + 1]), tw->line_color_1);
        }
    }
    if (is_show_y2) {
        for (int i = 0; i < tw->pointsNumber2 - 1; i++)
        {
            draw_line(TwoFunction_get_funcx_in_pic(tw, tw->x2[i]), TwoFunction_get_funcy2_in_pic(tw, tw->y2[i]),
                TwoFunction_get_funcx_in_pic(tw, tw->x2[i + 1]), TwoFunction_get_funcy2_in_pic(tw, tw->y2[i + 1]), tw->line_color_2);
        }
    }
}

//////////////////////////      下面是刻度文本选相关代码。            /////////////////////////////////

/// <summary>
/// 获取浮点数的整数部分长度。即小数点前面的位数。
/// </summary>
/// <param name="d">浮点数</param>
/// <returns>整数部分长度</returns>
int get_integer_count(float d)
{
    d = d > 0 ? d : -d;
    int i = 1;   //0.031，也有1位整数位。
    while (d > 10)
    {
        i++;
        d /= 10;
    }
    return i;
}

/// <summary>
/// 获取浮点数的小数点的位数。即浮点数前面0的个数。
/// </summary>
/// <param name="d">浮点数</param>
/// <returns>浮点数前面0的个数。</returns>
int get_decimal_count(float d)
{
    //大于1的浮点数前面是没有0的。如3.14前面没有0,0.03前面有两个0.
    d = d > 0 ? d : -d;
    int i = 0;
    while (d < 1)
    {
        i++;
        d *= 10;
    }
    return i;
}

/// <summary>
/// 横坐标居中显示字符串
/// </summary>
/// <param name="x">字符串中点位置的x轴坐标</param>
/// <param name="y">字符串顶部y轴坐标</param>
/// <param name="str">字符串</param>
/// <param name="str_Length">字符串长度</param>
/// <param name="font">文本格式</param>
void drawString_xcenter(int x, int y, char* str, int str_Length, TextFont font)
{
    x = x - (str_Length * (int)font.size / 4);
    draw_string(x, y, str, str_Length, font);
    //draw_string(x, y, str, str_Length, font);
}

/// <summary>
/// 纵坐标居中显示字符串（左对齐）
/// </summary>
/// <param name="x">字符串左边的坐标</param>
/// <param name="y">字符串中点位置的y轴坐标</param>
/// <param name="str">字符串</param>
/// <param name="str_Length">字符串长度</param>
/// <param name="font">文本格式</param>
void drawString_ycenter(int x, int y, char* str, int str_Length, TextFont font)
{
    y = y - (font.size / 2);
    draw_string(x, y, str, str_Length, font);
    //draw_string(x, y, str, str_Length, font);
}

/// <summary>
/// 纵坐标居中显示字符串（右对齐）
/// </summary>
/// <param name="right">字符串右端点的坐标</param>
/// <param name="y">字符串中点位置的y轴坐标</param>
/// <param name="str">字符串</param>
/// <param name="str_Length">字符串长度</param>
/// <param name="font">文本格式</param>
void drawString_ycenter_right(int right, int y, char* str, int str_Length, TextFont font)
{
    y = y - (font.size / 2);
    int x = right - ((str_Length + 1) * font.size / 2);
    // font->textMode = 1;
    draw_string(x, y, str, str_Length, font);
    //draw_string(x, y, str, str_Length, font);
}

/// <summary>
/// 初始化y轴刻度。左右两边都显示刻度。
/// </summary>
void TwoFunction_init_yscale_leftright(TwoFunction* tw)
{
    tw->scale_gap = 10 < (tw->scalefont.size * 1.2f) ? 10 : (tw->scalefont.size * 1.2f);  //刻度文本间隔至少10个像素点
    tw->yscale_number = ((tw->y1scale_area.height) / (tw->scalefont.size + tw->scale_gap));
    if (tw->yscale_number % 2 == 0)tw->yscale_number -= 1;      // yscale_number是奇数。下面计算方便
        
    tw->scale_gap = tw->y1scale_area.height / tw->yscale_number;    // 刻度文本的“实际高度”

    //这时yscale_number是文本限制的数量。
    //根据y的最值y_min, y_max和yscale_number计算y轴相邻刻度的差值 delta_y。
    {
        if (tw->yscale_number >= 3) tw->delta_y1 = (tw->y1_max - tw->y1_min) / (tw->yscale_number - 2);
        else                        tw->delta_y1 = (tw->y1_max - tw->y1_min);

        //寻找delta_y会在哪个区间。
        float a = 1;
        while (1)
        {
            if (tw->delta_y1 < a)                             a = a / 10;
            else if (tw->delta_y1 >= a * 10)                  a = a * 10;
            else if (tw->delta_y1 >= a && tw->delta_y1 < a * 10)   break;  //如果在这个区间，跳出循环。
        }
        //从2a,5a，10a中选取区间。向上取。刻度选大一些，数量才不用那么多，才放得下。
        if (tw->delta_y1 < 2 * a) tw->delta_y1 = 2 * a;
        else if (tw->delta_y1 < 5 * a) tw->delta_y1 = 5 * a;
        else  tw->delta_y1 = 10 * a;
    }
    {
        if (tw->yscale_number >= 3) tw->delta_y2 = (tw->y2_max - tw->y2_min) / (tw->yscale_number - 2);
        else                        tw->delta_y2 = (tw->y2_max - tw->y2_min);
        //寻找delta_y会在哪个区间。
        float a = 1;
        while (1)
        {
            if (tw->delta_y2 < a)                             a = a / 10;
            else if (tw->delta_y2 >= a * 10)                  a = a * 10;
            else if (tw->delta_y2 >= a && tw->delta_y2 < a * 10)   break;  //如果在这个区间，跳出循环。
        }
        //从2a,5a，10a中选取区间。向上取。刻度选大一些，数量才不用那么多，才放得下。
        if (tw->delta_y2 < 2 * a) tw->delta_y2 = 2 * a;
        else if (tw->delta_y2 < 5 * a) tw->delta_y2 = 5 * a;
        else  tw->delta_y2 = 10 * a;
    }

    //初始化刻度的函数值与在图片上的值。与计算y的最大最小值

    float y1_mid = (tw->y1_max + tw->y1_min) / 2;              //中点函数值
    int n1_dy = Round(y1_mid / tw->delta_y1);               //中点刻度的序号
    tw->y1_min = n1_dy * tw->delta_y1 - (tw->yscale_number / 2 + 0.5f) * tw->delta_y1;                  //函数区底部的刻度值
    //y1_max = n1_dy + (yscale_number / 2) * delta_y1;                           
    tw->y1_max = tw->y1_min + ((float)tw->y1scale_area.height / tw->scale_gap) * tw->delta_y1;      //函数区顶部的刻度值

    float y2_mid = (tw->y2_max + tw->y2_min) / 2;              //中点函数值
    int n2_dy = Round(y2_mid / tw->delta_y2);               //中点刻度的序号
    tw->y2_min = n2_dy * tw->delta_y2 - (tw->yscale_number / 2 + 0.5f) * tw->delta_y2;                  //函数区底部的刻度值
    tw->y2_max = tw->y2_min + ((float)tw->y1scale_area.height / tw->scale_gap) * tw->delta_y2;      //函数区顶部的刻度值


    int y1scale_textLength = 0;                    //刻度的文本长度。即刻度的整数位+小数位+符号位
    y1scale_textLength += get_decimal_count(tw->delta_y1);
    y1scale_textLength += get_integer_count(tw->y1_max);
    y1scale_textLength += 3;                       //加上小数点和符号位的长度，再加上最后一个空格符。
    y1scale_textLength = (y1scale_textLength * tw->scalefont.size / 2);  //文本的像素数长度

    int y2scale_textLength = 0;                    //刻度的文本长度。即刻度的整数位+小数位+符号位
    y2scale_textLength += get_decimal_count(tw->delta_y2);
    y2scale_textLength += get_integer_count(tw->y2_max);
    y2scale_textLength += 2;                       //加上小数点和符号位的长度。
    y2scale_textLength = (y2scale_textLength * tw->scalefont.size / 2);  //文本的像素数长度

    //根据y轴刻度文本长度完成4个区域的初始化。主要是left和right
    tw->y1scale_area.right = tw->left + y1scale_textLength + tw->scale_curve_gap;
    tw->y1scale_area.width = y1scale_textLength + tw->scale_curve_gap;
    tw->y2scale_area.left = tw->right - y2scale_textLength - tw->scale_curve_gap;
    tw->y2scale_area.width = y2scale_textLength + tw->scale_curve_gap;
    tw->xscale_area.left = tw->left + y1scale_textLength + tw->scale_curve_gap;
    tw->xscale_area.right = tw->right - y2scale_textLength - tw->scale_curve_gap;
    tw->xscale_area.width = tw->xscale_area.right - tw->xscale_area.left;
    tw->curveArea.left = tw->left + y1scale_textLength + tw->scale_curve_gap;
    tw->curveArea.right = tw->right - y2scale_textLength - tw->scale_curve_gap;
    tw->curveArea.width = tw->curveArea.right - tw->curveArea.left;

}

/// <summary>
/// 初始化y轴刻度。左边显示刻度。
/// </summary>
void TwoFunction_init_yscale_left(TwoFunction* tw)
{
    tw->scale_gap = 10 < (tw->scalefont.size * 1.2f) ? 10 : (tw->scalefont.size * 1.2f);  //刻度文本间隔至少10个像素点
    tw->yscale_number = ((tw->y1scale_area.height) / (tw->scalefont.size + tw->scale_gap));
    if (tw->yscale_number % 2 == 0)tw->yscale_number -= 1;      // yscale_number是奇数。下面计算方便
    tw->scale_gap = tw->y1scale_area.height / tw->yscale_number;    // 刻度文本的“实际高度”

    tw->y1_max = tw->y1_max > tw->y2_max ? tw->y1_max : tw->y2_max;
    tw->y1_min = tw->y1_min < tw->y2_min ? tw->y1_min : tw->y2_min;
    tw->y2_max = tw->y1_max > tw->y2_max ? tw->y1_max : tw->y2_max;
    tw->y2_min = tw->y1_min < tw->y2_min ? tw->y1_min : tw->y2_min;
    //这时yscale_number是文本限制的数量。
    //根据y的最值y_min, y_max和yscale_number计算y轴相邻刻度的差值 delta_y。
    {
        if (tw->yscale_number >= 3) tw->delta_y1 = (tw->y1_max - tw->y1_min) / (tw->yscale_number - 2);
        else                   tw->delta_y1 = (tw->y1_max - tw->y1_min);
        //寻找delta_y会在哪个区间。
        float a = 1;
        while (1)
        {
            if (tw->delta_y1 < a)                             a = a / 10;
            else if (tw->delta_y1 >= a * 10)                  a = a * 10;
            else if (tw->delta_y1 >= a && tw->delta_y1 < a * 10)  break;  //如果在这个区间，跳出循环。
        }
        //从2a,5a，10a中选取区间。向上取。刻度选大一些，数量才不用那么多，才放得下。
        if (tw->delta_y1 < 2 * a) tw->delta_y1 = 2 * a;
        else if (tw->delta_y1 < 5 * a) tw->delta_y1 = 5 * a;
        else  tw->delta_y1 = 10 * a;
    }
    {
        if (tw->yscale_number >= 3) tw->delta_y2 = (tw->y2_max - tw->y2_min) / (tw->yscale_number - 2);
        else                 tw->delta_y2 = (tw->y2_max - tw->y2_min);
        //寻找delta_y会在哪个区间。
        float a = 1;
        while (1)
        {
            if (tw->delta_y2 < a)                             a = a / 10;
            else if (tw->delta_y2 >= a * 10)                  a = a * 10;
            else if (tw->delta_y2 >= a && tw->delta_y2 < a * 10)   break;  //如果在这个区间，跳出循环。
        }
        //从2a,5a，10a中选取区间。向上取。刻度选大一些，数量才不用那么多，才放得下。
        if (tw->delta_y2 < 2 * a) tw->delta_y2 = 2 * a;
        else if (tw->delta_y2 < 5 * a) tw->delta_y2 = 5 * a;
        else tw->delta_y2 = 10 * a;
    }

    //初始化刻度的函数值与在图片上的值。与计算y的最大最小值

    float y1_mid = (tw->y1_max + tw->y1_min) / 2;              //中点函数值
    int n1_dy = Round(y1_mid / tw->delta_y1);               //中点刻度的序号
    tw->y1_min = n1_dy * tw->delta_y1 - (tw->yscale_number / 2 + 0.5f) * tw->delta_y1;           //函数区底部的函数值。这里0.5f补偿底部半个刻度。
    tw->y1_max = tw->y1_min + ((float)tw->y1scale_area.height / tw->scale_gap) * tw->delta_y1;      //函数区底部的函数值

    float y2_mid = (tw->y2_max + tw->y2_min) / 2;              //中点函数值
    int n2_dy = Round(y2_mid / tw->delta_y2);               //中点刻度的序号
    tw->y2_min = n2_dy * tw->delta_y2 - (tw->yscale_number / 2 + 0.5f) * tw->delta_y2;           //函数区底部的函数值。这里0.5f补偿底部半个刻度。
    tw->y2_max = tw->y2_min + ((float)tw->y1scale_area.height / tw->scale_gap) * tw->delta_y2;      //函数区底部的函数值


    //for (int i = 0; i < tw->yscale_number; i++)
    //{
    //    tw->scale_y_pic[i] = tw->curveArea.bottom - scale_gap * (0.5f + i);  //y的刻度从底部半个间隔开始。
    //    tw->scale_y1_func[i] = (n1_dy + i - tw->yscale_number / 2) * tw->delta_y1;
    //    tw->scale_y2_func[i] = (n2_dy + i - tw->yscale_number / 2) * tw->delta_y2;
    //}

    int y1scale_textLength = 0;                    //刻度的文本长度。即刻度的整数位+小数位+符号位
    y1scale_textLength += get_decimal_count(tw->delta_y1);
    y1scale_textLength += get_integer_count(tw->y1_max);
    y1scale_textLength += 3;                       //加上小数点和符号位的长度，再加上最后一个空格符。
    y1scale_textLength = (y1scale_textLength * tw->scalefont.size / 2);  //文本的像素数长度
         
    int y2scale_textLength = 0;                    //刻度的文本长度。即刻度的整数位+小数位+符号位
    y2scale_textLength += get_decimal_count(tw->delta_y2);
    y2scale_textLength += get_integer_count(tw->y2_max);
    y2scale_textLength += 2;                       //加上小数点和符号位的长度。
    y2scale_textLength = (y2scale_textLength * tw->scalefont.size / 2);  //文本的像素数长度
    y2scale_textLength = 0;                    //刻度的文本长度。即刻度的整数位+小数位+符号位

    //根据y轴刻度文本长度完成4个区域的初始化。
    tw->y1scale_area.right = tw->left + y1scale_textLength + tw->scale_curve_gap;
    tw->y1scale_area.width = y1scale_textLength + tw->scale_curve_gap;
    tw->y2scale_area.left = tw->right - y2scale_textLength - tw->scale_curve_gap;
    tw->y2scale_area.width = y2scale_textLength + tw->scale_curve_gap;
    tw->xscale_area.left = tw->left + y1scale_textLength + tw->scale_curve_gap;
    tw->xscale_area.right = tw->right - y2scale_textLength - tw->scale_curve_gap;
    tw->xscale_area.width = tw->xscale_area.right - tw->xscale_area.left;
    tw->curveArea.left = tw->left + y1scale_textLength + tw->scale_curve_gap;
    tw->curveArea.right = tw->right - y2scale_textLength - tw->scale_curve_gap;
    tw->curveArea.width = tw->curveArea.right - tw->curveArea.left;

    //初始化points
    //根据函数数组x，y初始化points。points在图片上的点与函数的点一一对应。

    //for (int i = 0; i < pointsNumber1; i++)
    //{
    //    points1[i].x = get_funcx_in_pic(x1[i]);
    //    points1[i].y = get_funcy1_in_pic(y1[i]);
    //}
    //for (int i = 0; i < pointsNumber2; i++)
    //{
    //    points2[i].x = get_funcx_in_pic(x2[i]);
    //    points2[i].y = get_funcy2_in_pic(y2[i]);
    //}

}

/// <summary>
/// 初始化y轴刻度。右边显示刻度。
/// </summary>
void TwoFunction_init_yscale_right(TwoFunction* tw)
{
    tw->scale_gap = 10 < (tw->scalefont.size * 1.2f) ? 10 : (tw->scalefont.size * 1.2f);  //刻度文本间隔至少10个像素点
    tw->yscale_number = ((tw->y1scale_area.height) / (tw->scalefont.size + tw->scale_gap));
    if (tw->yscale_number % 2 == 0)tw->yscale_number -= 1;      // tw->yscale_number是奇数。下面计算方便
    tw->scale_gap = tw->y1scale_area.height / tw->yscale_number;    // 刻度文本的“实际高度”

    tw->y1_max = tw->y1_max > tw->y2_max ? tw->y1_max : tw->y2_max;
    tw->y1_min = tw->y1_min < tw->y2_min ? tw->y1_min : tw->y2_min;
    tw->y2_max = tw->y1_max > tw->y2_max ? tw->y1_max : tw->y2_max;
    tw->y2_min = tw->y1_min < tw->y2_min ? tw->y1_min : tw->y2_min;
    //这时tw->yscale_number是文本限制的数量。
    //根据y的最值y_min, y_max和tw->yscale_number计算y轴相邻刻度的差值 tw->delta_y。
    {
        if (tw->yscale_number >= 3) tw->delta_y1 = (tw->y1_max - tw->y1_min) / (tw->yscale_number - 2);
        else                    tw->delta_y1 = (tw->y1_max - tw->y1_min);

        //寻找tw->delta_y会在哪个区间。
        float a = 1;
        while (1)
        {
            if (tw->delta_y1 < a)                             a = a / 10;
            else if (tw->delta_y1 >= a * 10)                  a = a * 10;
            else if (tw->delta_y1 >= a && tw->delta_y1 < a * 10)  break;  //如果在这个区间，跳出循环。
        }
        //从2a,5a，10a中选取区间。向上取。刻度选大一些，数量才不用那么多，才放得下。
        if (tw->delta_y1 < 2 * a) tw->delta_y1 = 2 * a;
        else if (tw->delta_y1 < 5 * a) tw->delta_y1 = 5 * a;
        else  tw->delta_y1 = 10 * a;
    }
    {
        if (tw->yscale_number >= 3) tw->delta_y2 = (tw->y2_max - tw->y2_min) / (tw->yscale_number - 2);
        else                    tw->delta_y2 = (tw->y2_max - tw->y2_min);

        //寻找tw->delta_y会在哪个区间。
        float a = 1;
        while (1)
        {
            if (tw->delta_y2 < a)                             a = a / 10;
            else if (tw->delta_y2 >= a * 10)                  a = a * 10;
            else if (tw->delta_y2 >= a && tw->delta_y2 < a * 10)   break;  //如果在这个区间，跳出循环。
        }
        //从2a,5a，10a中选取区间。向上取。刻度选大一些，数量才不用那么多，才放得下。
        if (tw->delta_y2 < 2 * a) tw->delta_y2 = 2 * a;
        else if (tw->delta_y2 < 5 * a) tw->delta_y2 = 5 * a;
        else  tw->delta_y2 = 10 * a;
    }

    //初始化刻度的函数值与在图片上的值。与计算y的最大最小值

    float y1_mid = (tw->y1_max + tw->y1_min) / 2;              //中点函数值
    int n1_dy = Round(y1_mid / tw->delta_y1);               //中点刻度的序号。即中点在下面往上数的第几个刻度。
    tw->y1_min = n1_dy * tw->delta_y1 - (tw->yscale_number / 2 + 0.5f) * tw->delta_y1;                  //函数区底部的刻度值
    tw->y1_max = tw->y1_min + ((float)tw->y1scale_area.height / tw->scale_gap) * tw->delta_y1;      //函数区顶部的刻度值

    float y2_mid = (tw->y2_max + tw->y2_min) / 2;              //中点函数值
    int n2_dy = Round(y2_mid / tw->delta_y2);               //中点刻度的序号
    tw->y2_min = n2_dy * tw->delta_y2 - (tw->yscale_number / 2 + 0.5f) * tw->delta_y2;                  //函数区底部的刻度值
    tw->y2_max = tw->y2_min + ((float)tw->y1scale_area.height / tw->scale_gap) * tw->delta_y2;      //函数区顶部的刻度值


    //for (int i = 0; i < tw->yscale_number; i++)
    //{
    //    tw->scale_y_pic[i] = curveArea.bottom - scale_gap * (0.5f + i);  //y的刻度从底部半个间隔开始。
    //    tw->scale_y1_func[i] = (n1_dy + i - tw->yscale_number / 2) * tw->delta_y1;
    //    tw->scale_y2_func[i] = (n2_dy + i - tw->yscale_number / 2) * tw->delta_y2;
    //}

    int y1scale_textLength = 0;                    //刻度的文本长度。即刻度的整数位+小数位+符号位
    y1scale_textLength += get_decimal_count(tw->delta_y1);
    y1scale_textLength += get_integer_count(tw->y1_max);
    y1scale_textLength += 3;                       //加上小数点和符号位的长度，再加上最后一个空格符。
    y1scale_textLength = (y1scale_textLength * tw->scalefont.size / 2);  //文本的像素数长度
    y1scale_textLength = 0;                    //刻度的文本长度。即刻度的整数位+小数位+符号位

    int y2scale_textLength = 0;                    //刻度的文本长度。即刻度的整数位+小数位+符号位
    y2scale_textLength += get_decimal_count(tw->delta_y2);
    y2scale_textLength += get_integer_count(tw->y2_max);
    y2scale_textLength += 2;                       //加上小数点和符号位的长度。
    y2scale_textLength = (y2scale_textLength * tw->scalefont.size / 2);  //文本的像素数长度

    //根据y轴刻度文本长度完成4个区域的初始化。
    tw->y1scale_area.right = tw->left + y1scale_textLength + tw->scale_curve_gap;
    tw->y1scale_area.width = y1scale_textLength + tw->scale_curve_gap;
    tw->y2scale_area.left = tw->right - y2scale_textLength - tw->scale_curve_gap;
    tw->y2scale_area.width = y2scale_textLength + tw->scale_curve_gap;
    tw->xscale_area.left = tw->left + y1scale_textLength + tw->scale_curve_gap;
    tw->xscale_area.right = tw->right - y2scale_textLength - tw->scale_curve_gap;
    tw->xscale_area.width = tw->xscale_area.right - tw->xscale_area.left;
    tw->curveArea.left = tw->left + y1scale_textLength + tw->scale_curve_gap;
    tw->curveArea.right = tw->right - y2scale_textLength - tw->scale_curve_gap;
    tw->curveArea.width = tw->curveArea.right - tw->curveArea.left;

    //初始化points
    //根据函数数组x，y初始化points。points在图片上的点与函数的点一一对应。

}

/// <summary>
/// 根据y轴的最大最小值，函数绘图区的高度，初始化并绘制y轴刻度。
/// 确定刻度大小后，确定刻度需要的宽度，确定绘图区的宽度，然后初始化points数组
/// </summary>
void TwoFunction_init_yscale(TwoFunction* tw)
{
    if (tw->yscaleFont == 1)
    {
        TwoFunction_init_yscale_left(tw);
    }
    else if(tw->yscaleFont==0)
    {
        TwoFunction_init_yscale_leftright(tw);
    }
    else 
    {
        TwoFunction_init_yscale_right(tw);
    }
}


/// <summary>
/// 根据x轴的最大最小值，函数绘图区的宽度，初始化并绘制x轴刻度。
/// </summary>
void TwoFunction_init_xscale(TwoFunction* tw)
{
    float dx = tw->x_max - tw->x_min;

    int xscale_textLength = 0;                    //刻度的文本长度。即刻度的整数位+小数位+符号位
    xscale_textLength += get_decimal_count(dx);
    xscale_textLength += get_integer_count(tw->x_max);
    xscale_textLength += 2;                       //加上小数点和符号位的长度。
    xscale_textLength += 1;                       //再加上刻度之间的空格。

    if (tw->xscaleFont == 1)  xscale_textLength = 10;  // 时间字符串： xx/xx/xx 加上前后两个空格，10字符
    xscale_textLength = (xscale_textLength * tw->scalefont.size / 2);       //文本的像素数长度
    tw->xscale_number = ((tw->xscale_area.width) / (xscale_textLength));

    //这时tw->xscale_number是文本限制的数量。
    //根据x的最值tw->x_min, tw->x_max和tw->xscale_number计算x轴相邻刻度的差值tw->delta_x。
    //下面初始化了tw->delta_x，tw->xscale_number可能不需要那么多。
    //这时要更新tw->xscale_number以保证图片的刻度分布均匀。
    if (tw->xscaleFont == 0)
    {
        if (tw->xscale_number > 1) tw->delta_x = (tw->x_max - tw->x_min) / (tw->xscale_number - 1);
        else  tw->delta_x = (tw->x_max - tw->x_min);
        //寻找tw->delta_x会在哪个区间。
        float a = 1;
        while (1)
        {
            if (tw->delta_x < a)                            a = a / 10;
            else if (tw->delta_x >= a * 10)                 a = a * 10;
            else if (tw->delta_x >= a && tw->delta_x < a * 10)  break;  //如果在这个区间，跳出循环。
        }
        //从2a,5a，10a中选取区间。向上取。
        if (tw->delta_x < 2 * a) tw->delta_x = 2 * a;
        else if (tw->delta_x < 5 * a) tw->delta_x = 5 * a;
        else tw->delta_x = 10 * a;

        //因为tw->delta_x重新设定了，所以tw->xscale_number也要重新设定。
        tw->xscale_number = ((tw->x_max - tw->x_min) / tw->delta_x + 1) < tw->xscale_number ? ((tw->x_max - tw->x_min) / tw->delta_x + 1) : tw->xscale_number;
    }
    else {
        tw->delta_x = (tw->x_max_ - tw->x_min_) / (tw->xscale_number - 1);
    }
}

/// <summary>
/// 整形转字符串。  静态函数，只在这个文件内部可用。其他文件可以定义相同名字的函数，不会发生冲突。
/// </summary>
/// <param name="val">待转换的数据</param>
/// <param name="str">转换的字符串，左对齐。如果字符串长度不够，只记录高位。</param>
/// <param name="str_width">字符串的宽度。包含一个符号位,一个小数点。实际显示的数字只有str_width-2位。</param>
/// <param name="decimal">小数点显示的位数</param>
/// <returns>数字转换成字符串的长度，这里是左对齐，因此右边会有不少空格</returns>
static int float_to_str_left_s(float val, char* str, int str_width, int decimal)
{
    //整数位数不确定，但可以立刻知道个位是什么，所以这里先将字符串倒过来
    char digval;    //中间变量，记录位的值。
    char sign;      //符号位
    char tstr[18];  //临时字符串。转换后的数字先放这里，再转换到str。32的int型只有10位，浮点数最多6位小数。18位够了。
    int len;    //记录已转换的字符串tstr的长度
    int ival;
    int ival0;
    len = 0;
    if (val >= 0) {
        sign = 0;
    }
    else {
        val = -val;
        sign = 1;
    }
    if (decimal > 6)decimal = 6;  //浮点数最多有6位小数。

    ival0 = (int)(val);    //整数部分。
    //先转换小数部分：
    if (decimal > 0)
    {
        //先按照显示的小数位数把浮点数的小数部分放大，变成整数，然后在右边第decimal位的位置加上小数点。
        int ex; //  = powi(10, decimal);
        {
            int base, exponent, a, i;
            base = 10;
            exponent = decimal;
            a = 1;
	        for (i = 0; i < exponent; i++) {
		        a *= base;
	        }
            ex = a;
        }

        ival = (int)((val - (int)val) * ex + 0.5f);   //小数部分四舍五入
        if (ival / ex >= 1) {
            ival0 += (ival / ex);   //四舍五入如果进位到了整数，则需要给整数部分增加。
            ival = ival % ex;
        }
        do {
            digval = ival % 10;
            ival /= 10;
            tstr[len] = (char)(digval + '0');
            len++;
        } while (ival > 0);
        //这里注意：前面需要填充0字符。不然会出错。
        while (len < decimal)
        {
            tstr[len] = '0';
            len++;
        }
        tstr[len] = '.';
        len++;
    }
    //转换整数部分
    ival = ival0;
    do {
        digval = ival % 10;
        ival /= 10;
        tstr[len] = (char)(digval + '0');
        len++;
    } while (ival > 0);
    if (sign == 0) {
        tstr[len] = ' ';
        len++;
    }
    else {
        tstr[len] = '-';
        len++;
    }

    //下面将tstr的内容复制到str
    if (len > str_width) {
        int i = 0;
        for (i = 0; i < str_width; i++) {
            str[i] = tstr[len - i - 1];
        }
    }
    else {     //左对齐，右边填充空格。
        int i = 0;
        for (i = 0; i < len; i++) {
            str[i] = tstr[len - i - 1];
        }
        for (i = len; i < str_width; i++) {
            str[i] = ' ';
        }
    }
    return len;
}
//

/// <summary>
/// 绘制刻度。绘制前需要初始化xy的刻度。 
/// </summary>
/// <param name="is_drawMainGridLine">是否绘制网格线。1：绘制；0：不绘制</param>
void TwoFunction_draw_scale(TwoFunction* tw, int is_drawMainGridLine)
{
    //先绘制坐标轴
    draw_line(tw->curveArea.left, tw->curveArea.top, tw->curveArea.left, tw->curveArea.bottom, tw->xy_line_color);  //绘制坐标轴
    draw_line(tw->curveArea.right, tw->curveArea.top, tw->curveArea.right, tw->curveArea.bottom, tw->xy_line_color);  //绘制坐标轴
    draw_line(tw->curveArea.left, tw->curveArea.bottom, tw->curveArea.right, tw->curveArea.bottom, tw->xy_line_color);  //绘制坐标轴

    char str[32];  //缓存刻度文本
    int str_Length;   //刻度文本的实际长度
    int scale_x_strDecimalLen = get_decimal_count(tw->delta_x); //获取刻度的小数点位数
    int scale_y1_strDecimalLen = get_decimal_count(tw->delta_y1); //获取刻度的小数点位数
    int scale_y2_strDecimalLen = get_decimal_count(tw->delta_y2); //获取刻度的小数点位数
    if (tw->xscaleFont == 0) {
        int scale_x_pic;
        float scale_x_func;

        for (int i = 0; i < tw->xscale_number; i++)
        {
            scale_x_func = ((int)(tw->x_min / tw->delta_x) + i) * tw->delta_x;
            scale_x_pic = TwoFunction_get_funcx_in_pic(tw, scale_x_func);

            if (scale_x_pic > tw->curveArea.left && scale_x_pic < tw->curveArea.right) {
                if (is_drawMainGridLine)
                    draw_line(scale_x_pic, tw->curveArea.top, scale_x_pic, tw->curveArea.bottom, tw->grid_line_color);  //绘制网格线

                str_Length = float_to_str_left_s(scale_x_func, str, 32, scale_x_strDecimalLen);
                if (scale_x_pic + (str_Length + 1) * tw->scalefont.size / 4 <= tw->right)
                {
                    drawString_xcenter(scale_x_pic, tw->xscale_area.top, str, str_Length, tw->scalefont);
                }
            }
        }
    }

    float y1_mid = (tw->y1_max + tw->y1_min) / 2;              //中点函数值
    int n1_dy = Round(y1_mid / tw->delta_y1);               //中点刻度的序号
    float y2_mid = (tw->y2_max + tw->y2_min) / 2;              //中点函数值
    int n2_dy = Round(y2_mid / tw->delta_y2);               //中点刻度的序号
    float scale_y_pic;
    float scale_y1_func;
    float scale_y2_func;

    if (tw->yscaleFont == 1) {

        for (int i = 0; i < tw->yscale_number; i++)
        {
            scale_y_pic = tw->curveArea.bottom - tw->scale_gap * (0.5f + i);  //y的刻度从底部半个间隔开始。
            scale_y1_func = (n1_dy + i - tw->yscale_number / 2) * tw->delta_y1;
            if (scale_y_pic > tw->curveArea.top && scale_y_pic < tw->curveArea.bottom) {
                if (is_drawMainGridLine)
                    draw_line(tw->curveArea.left, scale_y_pic, tw->curveArea.right, scale_y_pic, tw->grid_line_color); //绘制网格线

                str_Length = float_to_str_left_s(scale_y1_func, str, 32, scale_y1_strDecimalLen);
                if (scale_y_pic - tw->scalefont.size / 2 - 2 > tw->y1scale_area.top &&
                    scale_y_pic + tw->scalefont.size / 2 + 2 < tw->y1scale_area.bottom + tw->scale_curve_gap) {
                    drawString_ycenter_right(tw->y1scale_area.right, scale_y_pic, str, str_Length, tw->scalefont);
                }
            }
        }
    }
    else if (tw->yscaleFont == 0) {
        for (int i = 0; i < tw->yscale_number; i++)
        {
            scale_y_pic = tw->curveArea.bottom - tw->scale_gap * (0.5f + i);  //y的刻度从底部半个间隔开始。
            scale_y1_func = (n1_dy + i - tw->yscale_number / 2) * tw->delta_y1;
            scale_y2_func = (n2_dy + i - tw->yscale_number / 2) * tw->delta_y2;
            if (scale_y_pic > tw->curveArea.top && scale_y_pic < tw->curveArea.bottom) {
                if (is_drawMainGridLine)
                    draw_line(tw->curveArea.left, scale_y_pic, tw->curveArea.right, scale_y_pic, tw->grid_line_color); //绘制网格线

                str_Length = float_to_str_left_s(scale_y1_func, str, 32, scale_y1_strDecimalLen);
                if (scale_y_pic - tw->scalefont.size / 2 - 2 > tw->y1scale_area.top &&
                    scale_y_pic + tw->scalefont.size / 2 + 2 < tw->y1scale_area.bottom + tw->scale_curve_gap) {
                    drawString_ycenter_right(tw->y1scale_area.right, scale_y_pic, str, str_Length, tw->scalefont);
                }
                str_Length = float_to_str_left_s(scale_y2_func, str, 32, scale_y2_strDecimalLen);
                if (scale_y_pic - tw->scalefont.size / 2 - 2 > tw->y2scale_area.top &&
                    scale_y_pic + tw->scalefont.size / 2 + 2 < tw->y2scale_area.bottom + tw->scale_curve_gap) {
                    drawString_ycenter(tw->y2scale_area.left, scale_y_pic, str, str_Length, tw->scalefont);
                }
            }
        }
    }
    else {
        for (int i = 0; i < tw->yscale_number; i++)
        {
            scale_y_pic = tw->curveArea.bottom - tw->scale_gap * (0.5f + i);  //y的刻度从底部半个间隔开始。
            scale_y2_func = (n2_dy + i - tw->yscale_number / 2) * tw->delta_y2;
            if (scale_y_pic > tw->curveArea.top && scale_y_pic < tw->curveArea.bottom) {
                if (is_drawMainGridLine)
                    draw_line(tw->curveArea.left, scale_y_pic, tw->curveArea.right, scale_y_pic, tw->grid_line_color); //绘制网格线

                str_Length = float_to_str_left(scale_y2_func, str, 32, scale_y2_strDecimalLen);
                if (scale_y_pic - tw->scalefont.size / 2 - 2 > tw->y2scale_area.top &&
                    scale_y_pic + tw->scalefont.size / 2 + 2 < tw->y2scale_area.bottom + tw->scale_curve_gap) {
                    drawString_ycenter(tw->y2scale_area.left, scale_y_pic, str, str_Length, tw->scalefont);
                }
            }
        }
    }

}

/*
    注意函数的使用顺序。
    drawFunction draw(graphic, functionAera, &scalefont);
    draw.init_func(x, y, n);  //必须第一个调用。初始化xy坐标点的函数值，确定最大最小值。 或者调用 TwoFunction_set_min_max（）
    
    draw.init_yscale();       //必须第二个调用。先根据y的函数值确定y轴刻度占据的宽度，才能计算x轴显示区域的宽度。
    draw.init_xscale();       //初始化了y的刻度文本，才能完全确定x刻度，完成曲线区的划分。这时才能调用get_funcx_in_pic函数。

    draw.draw_scale();     //绘制刻度
    draw.draw_points();    //选择绘制点的格式
    draw.draw_func();      //绘制函数。draw_points只画点，不连线。
    //
*/


/// <summary>
/// 2024.4.30 初步完成。
/// 快速绘制函数版本：直接用单像素点，更新数组的某个点时，直接消隐函数点，如果点在网格线上，用网格线颜色，否则是背景色。
/// 要求：函数点之间没有重合，否则会出错。同时，这个函数不会更新现有坐标系的最大最小值，绘制函数只能是不连线的形式。
/// 绘制函数连线是下一层结构体TwoFunctionPicture调用的。
/// 而且，要已经绘制了整个函数，才能调用快速绘制函数。
/// 
/// 2024.5.16  目前这个版本的绘图有个问题：下面的replace point 总会擦掉网格线。
/// 根本原因：网格线的图片位置不能整形计算，浮点计算存在一点点误差。
/// 造成这个问题的原因是：先定了边框的最大最小值，再定的浮点间隔值，间隔数量，再计算浮点网格线坐标。
/// 更好的思路是：先看数组最大最小值，估算浮点间隔值，间隔数量，先定好整型的deltaxy对应的像素数，及第一条网格线的坐标，再反过来定义边框上的函数值。
/// 画点的时候，先计算点对应的整形像素坐标，然后就可以没有浮点误差地判断点是否在网格线上。
/// 
/// 2024.5.20  按照5.16的思路修改，改动还是比较大，这里用个折中的办法，将TwoFunction_get_funcx_in_pic之类的函数返回值改为整形，
/// 能直接计算刻度坐标的直接计算对比，不能计算的就直接遍历坐标的整形点，看是否符合。
/// 我这个函数设计刻度线不会太多，800*800尺寸的图片最多20~30条刻度线。
/// </summary>
/// <param name="tw">函数结构体</param>
/// <param name="index">更换的点的索引</param>
/// <param name="nx">新点x轴函数值</param>
/// <param name="ny">新点y轴函数值</param>
/// <param name="is_y1">是否y1的函数，如果不是，就是y2的函数</param>
void TwoFunction_replace_point(TwoFunction* tw, int index, float nx, float ny, bool is_y1)
{
    bool is_on_grid_line = false;  // 看原来的点是否在网格线上。
    // 首先，刻度都是 1，2，5 之类的倍数。 如果函数值除以 delta_x，delta_y,是整数，说明在刻度上。

    if (is_y1) {

        int x = TwoFunction_get_funcx_in_pic(tw, tw->x1[index]);
        int y = TwoFunction_get_funcy1_in_pic(tw, tw->y1[index]);
 
        //  scale_y_pic = tw->curveArea.bottom - tw->scale_gap * (0.5f + i);  //y的刻度从底部半个间隔开始。
        if ((tw->curveArea.bottom - (int)(tw->scale_gap * 0.5f) - y) % tw->scale_gap == 0) {
            is_on_grid_line = true;
        }
        else
        {
            for (int i = 0; i < tw->xscale_number; i++)
            {
                float scale_x_func = ((int)(tw->x_min / tw->delta_x) + i) * tw->delta_x;
                int  scale_x_pic = TwoFunction_get_funcx_in_pic(tw, scale_x_func);
                if (x == scale_x_pic) is_on_grid_line = true;
            }
        }

        //消隐点
        if (is_on_grid_line)
            graphics_draw_point(x, y, tw->grid_line_color);
        else
            graphics_draw_point(x, y, tw->background);
        //更新点
        if (nx < tw->x_min)nx = tw->x_min;
        if (nx > tw->x_max)nx = tw->x_max;
        if (ny < tw->y1_min)ny = tw->y1_min;
        if (ny > tw->y1_max)ny = tw->y1_max;
        tw->x1[index] = nx;
        tw->y1[index] = ny;
        x = TwoFunction_get_funcx_in_pic(tw, tw->x1[index]);
        y = TwoFunction_get_funcy1_in_pic(tw, tw->y1[index]);
        graphics_draw_point(x, y, tw->point_color_1);
    }
    else
    {
        int x = TwoFunction_get_funcx_in_pic(tw, tw->x2[index]);
        int y = TwoFunction_get_funcy2_in_pic(tw, tw->y2[index]);

        if ((tw->curveArea.bottom - (int)(tw->scale_gap * 0.5f) - y) % tw->scale_gap == 0) {
            is_on_grid_line = true;
        }
        else {
            for (int i = 0; i < tw->xscale_number; i++)
            {
                float scale_x_func = ((int)(tw->x_min / tw->delta_x) + i) * tw->delta_x;
                int  scale_x_pic = TwoFunction_get_funcx_in_pic(tw, scale_x_func);
                if (x == scale_x_pic) is_on_grid_line = true;
            }
        }

        //消隐点
        if (is_on_grid_line)
            graphics_draw_point(x, y, tw->grid_line_color);
        else
            graphics_draw_point(x, y, tw->background);
        //更新点
        if (nx < tw->x_min)nx = tw->x_min;
        if (nx > tw->x_max)nx = tw->x_max;
        if (ny < tw->y2_min)ny = tw->y2_min;
        if (ny > tw->y2_max)ny = tw->y2_max;
        tw->x2[index] = nx;
        tw->y2[index] = ny;
        x = TwoFunction_get_funcx_in_pic(tw, tw->x2[index]);
        y = TwoFunction_get_funcy2_in_pic(tw, tw->y2[index]);
        graphics_draw_point(x, y, tw->point_color_2);
    }
}



/// <summary>
/// 初始化函数图片结构体
/// </summary>
/// <param name="tfw">函数图片结构体</param>
/// <param name="left">函数图片左侧x坐标</param>
/// <param name="top">函数图片顶部y坐标</param>
/// <param name="width">函数图片的宽度</param>
/// <param name="height">函数图片的高度</param>
void TwoFunctionPicture_init(TwoFunctionPicture* tfw, int left, int top, int width, int height)
{
    //绘制图表。图表有页边距，标题，X、Y轴标题与X、Y轴刻度。
    //图表格式：用户可自行设置的参数：
    //1、图片的宽，高。
    //2、标题，X、Y轴标题。
    //3、是否显示网格线。
    //4、函数数组

    tfw->left = left;
    tfw->top = top;
    tfw->picWidth = width;
    tfw->picHeight = height;

    //下面是绘制函数相关的变量与函数。
    tfw->draw.background = RGB_white; //背景颜色。
    tfw->draw.grid_line_color = RGB_lightgray; //网格线的颜色
    tfw->draw.xy_line_color = RGB_black;  //xy轴线的颜色
    tfw->draw.pointsize_1 = 9;      // 点的尺寸(点长宽占据的像素点)。
    tfw->draw.pointsize_2 = 9;      // 点的尺寸(点长宽占据的像素点)。
    tfw->draw.pointstyle_1 = 0;     // 点的形状。0 / 1 （实心 / 空心）圆形；2 / 3（实心 / 空心）正方形；4 / 5（实心 / 空心）三角形；
    tfw->draw.pointstyle_2 = 0;     // 点的形状。0 / 1 （实心 / 空心）圆形；2 / 3（实心 / 空心）正方形；4 / 5（实心 / 空心）三角形；
    tfw->draw.point_color_1 = RGB_blue; //点颜色。
    tfw->draw.point_color_2 = RGB_red; //点颜色。
    tfw->draw.line_color_1 = RGB_blue;   //线条颜色。
    tfw->draw.line_color_2 = RGB_red;  //线条颜色。

    tfw->titleFontSize = size16;             //标题字体大小。
    tfw->xytitleFontSize = size16;           //xy轴标题字体大小。
    tfw->scaleFontSize = size16;             //刻度字体大小

    tfw->titleFontColor = RGB_black;         //标题字体大小。
    tfw->xytitleFontColor = RGB_black;       //xy轴标题字体大小。
    tfw->scaleFontColor = RGB_black;         //刻度字体大小
    tfw->legendFontColor = RGB_black;        //刻度字体大小

    tfw->marginWidth = 5;    //横向的页边距。
    tfw->marginHeight = 5;   //纵向的页边距。margin： [ˈmɑːdʒɪn]  n.边缘;页边空白;白边;

    tfw->title_Length = 0;                       //标题长度。title_Length/2*FontSize就是标题文本的像素长度。
    tfw->xtitle_Length = 0;                      //x轴标题长度
    tfw->y1title_Length = 0;                     //y1标题长度
    tfw->y2title_Length = 0;                     //y2标题长度

}


// 用于测试是否正确分区。
void draw_rect_area(rect area, COLOR_RGB color)
{
    draw_rectangle(area.left, area.top, area.width, area.height, color);
}
void fill_rect_area(rect area, COLOR_RGB color)
{
    draw_solidrectangle(area.left, area.top, area.width, area.height, color);
}

//先初始化标题，xy轴标题的格式与文本，才能划分区域。
void TwoFunctionPicture_init_titleAera(TwoFunctionPicture* tfw)//初始化标题区
{
    tfw->titleAera.left = tfw->left + tfw->marginWidth;
    tfw->titleAera.top = tfw->top + tfw->marginHeight / 2;
    tfw->titleAera.right = tfw->left + tfw->picWidth - tfw->marginWidth;
    tfw->titleAera.bottom = tfw->titleAera.top + (tfw->titleFontSize);
    rect_get_width_height(&tfw->titleAera);
}
void TwoFunctionPicture_init_xtitleAera(TwoFunctionPicture* tfw)//初始化x轴标题区
{
    tfw->xtitleAera.right = tfw->left + tfw->picWidth - tfw->marginWidth;
    tfw->xtitleAera.bottom = tfw->top + tfw->picHeight - tfw->marginHeight;
    tfw->xtitleAera.left = tfw->xtitleAera.right - (tfw->xtitle_Length * tfw->xytitleFontSize / 2);
    tfw->xtitleAera.top =  tfw->xtitleAera.bottom - (tfw->xytitleFontSize);
    rect_get_width_height(&tfw->xtitleAera);
}
void TwoFunctionPicture_init_y1titleAera(TwoFunctionPicture* tfw)//初始化y轴标题区
{
    tfw->y1titleAera.left = tfw->left + tfw->marginWidth;
    tfw->y1titleAera.top = tfw->top + tfw->marginHeight + (tfw->titleFontSize);
    tfw->y1titleAera.right = tfw->left + tfw->y1titleAera.left + (tfw->y1title_Length * tfw->xytitleFontSize / 2);
    tfw->y1titleAera.bottom = tfw->y1titleAera.top + (tfw->xytitleFontSize);
    rect_get_width_height(&tfw->y1titleAera);
}
void TwoFunctionPicture_init_y2titleAera(TwoFunctionPicture* tfw)//初始化y轴标题区
{
    tfw->y2titleAera.right = tfw->left + tfw->picWidth - tfw->marginWidth;
    tfw->y2titleAera.top = tfw->top + tfw->marginHeight + (tfw->titleFontSize);
    tfw->y2titleAera.left = tfw->y2titleAera.right - (tfw->y2title_Length * tfw->xytitleFontSize / 2);
    tfw->y2titleAera.bottom = tfw->y2titleAera.top + (tfw->xytitleFontSize);
    rect_get_width_height(&tfw->y2titleAera);
}
void TwoFunctionPicture_init_functionAera(TwoFunctionPicture* tfw)//初始化函数区
{
    tfw->functionAera.right = tfw->left + tfw->picWidth - tfw->marginWidth;
    tfw->functionAera.bottom = tfw->top + tfw->picHeight - tfw->marginHeight - (tfw->xytitleFontSize);
    tfw->functionAera.left = tfw->left + tfw->marginWidth;
    tfw->functionAera.top = tfw->y1titleAera.bottom;
    rect_get_width_height(&tfw->functionAera);
}

/// <summary>
/// 先初始化文本格式、清空图片，然后初始化主标题，xy轴标题，根据标题大小划分区域，绘制坐标轴与标题。
/// </summary>
/// <param name="title_">图表标题</param>
/// <param name="xtitle_">x轴标题</param>
/// <param name="y1title_">y1的标题</param>
/// <param name="y2title_">y2标题</param>
void TwoFunctionPicture_draw_title(TwoFunctionPicture* tfw, const char* title_, const  char* xtitle_, const  char* y1title_, const char* y2title_)
{
    //先初始化文本格式
    tfw->titlefont.size = tfw->titleFontSize;
    tfw->titlefont.textMode = 0;
    tfw->titlefont.textColor = tfw->titleFontColor;
    tfw->scalefont.size = tfw->scaleFontSize;
    tfw->scalefont.textMode = 0;
    tfw->scalefont.textColor = tfw->scaleFontColor;
    tfw->xytitlefont.size = tfw->xytitleFontSize;
    tfw->xytitlefont.textMode = 0;
    tfw->xytitlefont.textColor = tfw->xytitleFontColor;
    //清空图片
    //graphic->clearIMA(background_color);
    graphics_fill_area(tfw->left, tfw->top, tfw->picWidth, tfw->picHeight, tfw->draw.background);

//    int i;
    //初始化标题文本
    tfw->title_Length = 0;           //标题长度
    tfw->xtitle_Length = 0;          //x轴标题长度
    tfw->y1title_Length = 0;          //y轴标题长度
    tfw->y2title_Length = 0;          //y轴标题长度

    while (title_[tfw->title_Length] != 0)
    {
        tfw->title[tfw->title_Length] = title_[tfw->title_Length];
        tfw->title_Length++;
        if (tfw->title_Length >= 31)break;
    }
    tfw->title[tfw->title_Length] = 0;

    while (xtitle_[tfw->xtitle_Length] != 0)
    {
        tfw->xtitle[tfw->xtitle_Length] = xtitle_[tfw->xtitle_Length];
        tfw->xtitle_Length++;
        if (tfw->xtitle_Length >= 31)break;
    }
    tfw->xtitle[tfw->xtitle_Length] = 0;

    while (y1title_[tfw->y1title_Length] != 0)
    {
        tfw->y1title[tfw->y1title_Length] = y1title_[tfw->y1title_Length];
        tfw->y1title_Length++;
        if (tfw->y1title_Length >= 31)break;
    }
    tfw->y1title[tfw->y1title_Length] = 0;

    while (y2title_[tfw->y2title_Length] != 0)
    {
        tfw->y2title[tfw->y2title_Length] = y2title_[tfw->y2title_Length];
        tfw->y2title_Length++;
        if (tfw->y2title_Length >= 31)break;
    }
    tfw->y2title[tfw->y2title_Length] = 0;

    //定下标题的内容后，即可初始化各个区域
    TwoFunctionPicture_init_titleAera(tfw);
    TwoFunctionPicture_init_xtitleAera(tfw);
    TwoFunctionPicture_init_y1titleAera(tfw);
    TwoFunctionPicture_init_y2titleAera(tfw);
    TwoFunctionPicture_init_functionAera(tfw);
    //draw_rect_area(tfw->titleAera, RGB_red);
    //draw_rect_area(tfw->xtitleAera, RGB_red);
    //draw_rect_area(tfw->y1titleAera, RGB_red);
    //draw_rect_area(tfw->y2titleAera, RGB_red);
    //draw_rect_area(tfw->functionAera, RGB_red);

        //绘制表格标题
    draw_string(
        tfw->titleAera.left + tfw->titleAera.width / 2 - (tfw->title_Length * tfw->titleFontSize / 4),
        tfw->titleAera.top,
        tfw->title,
        tfw->title_Length,
        tfw->titlefont);
    draw_string(tfw->y1titleAera.left, tfw->y1titleAera.top, tfw->y1title, tfw->y1title_Length, tfw->xytitlefont);
    draw_string(tfw->y2titleAera.left, tfw->y2titleAera.top, tfw->y2title, tfw->y2title_Length, tfw->xytitlefont);
    draw_string(tfw->xtitleAera.left, tfw->xtitleAera.top, tfw->xtitle, tfw->xtitle_Length, tfw->xytitlefont);

}

/// <summary>
/// 绘制函数
/// </summary>
/// <param name="x1">函数1的x坐标</param>
/// <param name="y1">函数1的y坐标</param>
/// <param name="n1">函数1的点个数</param>
/// <param name="x2">函数2的x坐标</param>
/// <param name="y2">函数2的y坐标</param>
/// <param name="n2">函数2的点个数</param>
/// <param name="isline">是否用线连接函数点。如果x坐标数组是从小到大排序好的，才可以用线连接</param>
/// <param name="yfont">x轴刻度显示的格式：= 0左右两边分别显示y1,y2的刻度；= 1左边显示刻度；= -1右边显示刻度。</param>
/// <param name="xfont">x轴刻度显示的格式：= 0显示为数字；= 1作为时间戳，显示的时候以时间的形式显示，这里没有实现这个功能，=1就先不显示x刻度。</param>
/// <param name="pointcolor1">函数y1的点颜色数组。如果有定义颜色数组，则用数组颜色，点的样式是空心圆。否则用默认颜色和样式</param>
/// <param name="pointcolor2">函数y2的点颜色数组。如果有定义颜色数组，则用数组颜色，点的样式是空心圆。否则用默认颜色和样式</param>
void TwoFunctionPicture_draw_func(TwoFunctionPicture* tfw,float* x1, float* y1, int n1, float* x2, float* y2, int n2,
    bool isline, int yfont, int xfont, COLOR_RGB* pointcolor1, COLOR_RGB* pointcolor2)
{
    graphics_fill_area(tfw->left , tfw->top , tfw->picWidth, tfw->picHeight, tfw->draw.background);
    draw_string(
        tfw->titleAera.left + tfw->titleAera.width / 2 - (tfw->title_Length * tfw->titleFontSize / 4),
        tfw->titleAera.top,
        tfw->title,
        tfw->title_Length,
        tfw->titlefont);
    draw_string(tfw->y1titleAera.left, tfw->y1titleAera.top, tfw->y1title, tfw->y1title_Length, tfw->xytitlefont);
    draw_string(tfw->y2titleAera.left, tfw->y2titleAera.top, tfw->y2title, tfw->y2title_Length, tfw->xytitlefont);
    draw_string(tfw->xtitleAera.left, tfw->xtitleAera.top, tfw->xtitle, tfw->xtitle_Length, tfw->xytitlefont);
    //绘制图例。 直接在 y1标题，y2标题后面跟这一个自己的位置，绘制图例
    TwoFunction_draw_point(tfw->y1titleAera.right+ tfw->draw.pointsize_1, tfw->y1titleAera.top + tfw->y1titleAera.height / 2,
        tfw->draw.pointsize_1, tfw->draw.pointstyle_1, tfw->draw.point_color_1);
    TwoFunction_draw_point(tfw->y2titleAera.left - tfw->draw.pointsize_2, tfw->y2titleAera.top + tfw->y1titleAera.height / 2,
        tfw->draw.pointsize_2, tfw->draw.pointstyle_2, tfw->draw.point_color_2);

    //绘制函数
    //TwoFunction draw = ; // (graphic, functionAera, &scalefont, xfont, yfont);

    TwoFunction_init(&tfw->draw, tfw->functionAera, &tfw->scalefont, xfont, yfont);

    //    graphics_fill_area(0, 0, tfw->picWidth, tfw->picHeight, tfw->background_color);
    // fill_rect_area(tfw->functionAera, tfw->background_color);

    //先初始化绘图样式。

    TwoFunction_init_func(&tfw->draw, x1, y1, n1, x2, y2, n2);
    TwoFunction_init_yscale(&tfw->draw);
    TwoFunction_init_xscale(&tfw->draw);

    TwoFunction_draw_scale(&tfw->draw,true);
    TwoFunction_draw_points(&tfw->draw,true, true, pointcolor1, pointcolor2); //选择绘制点的格式

    if (isline == true) {
        TwoFunction_draw_func(&tfw->draw, true, true);
    }


    //draw_rect_area(tfw->titleAera, RGB_red);
    //draw_rect_area(tfw->xtitleAera, RGB_red);
    //draw_rect_area(tfw->y1titleAera, RGB_red);
    //draw_rect_area(tfw->y2titleAera, RGB_red);
    //draw_rect_area(tfw->functionAera, RGB_red);

}


/// <summary>
/// 快速绘制函数
/// 快速绘制函数版本：直接用单像素点，更新数组的某个点时，直接消隐函数点，如果点在网格线上，用网格线颜色，否则是背景色。
/// 结合 TwoFunction_replace_point 使用。
/// </summary>
/// <param name="x1">函数1的x坐标</param>
/// <param name="y1">函数1的y坐标</param>
/// <param name="n1">函数1的点个数</param>
/// <param name="x2">函数2的x坐标</param>
/// <param name="y2">函数2的y坐标</param>
/// <param name="n2">函数2的点个数</param>
/// <param name="yfont">x轴刻度显示的格式：= 0左右两边分别显示y1,y2的刻度；= 1左边显示刻度；= -1右边显示刻度。</param>
/// <param name="xfont">x轴刻度显示的格式：= 0显示为数字；= 1作为时间戳，显示的时候以时间的形式显示，这里没有实现这个功能，=1就先不显示x刻度。</param>
/// <param name="is_set_min_max"> 是否设置坐标的极值 ==0，不设置，否则用下面的参数设置 </param>
/// <param name="xmin">x坐标值的最小值</param>
/// <param name="xmax">x坐标值的最大值</param>
/// <param name="y1min">y1坐标值的最小值</param>
/// <param name="y1max">y1坐标值的最大值</param>
/// <param name="y2min">y2坐标值的最小值</param>
/// <param name="y2max">y2坐标值的最大值</param>
void TwoFunctionPicture_fast_draw_func(TwoFunctionPicture* tfw,
    float* x1, float* y1, int n1, 
    float* x2, float* y2, int n2,
    int yfont, int xfont, int is_set_min_max,
    float xmin, float xmax, 
    float y1min, float y1max, 
    float y2min, float y2max)
{
    graphics_fill_area(tfw->left, tfw->top, tfw->picWidth, tfw->picHeight, tfw->draw.background);
    draw_string(
        tfw->titleAera.left + tfw->titleAera.width / 2 - (tfw->title_Length * tfw->titleFontSize / 4),
        tfw->titleAera.top,
        tfw->title,
        tfw->title_Length,
        tfw->titlefont);
    draw_string(tfw->y1titleAera.left, tfw->y1titleAera.top, tfw->y1title, tfw->y1title_Length, tfw->xytitlefont);
    draw_string(tfw->y2titleAera.left, tfw->y2titleAera.top, tfw->y2title, tfw->y2title_Length, tfw->xytitlefont);
    draw_string(tfw->xtitleAera.left, tfw->xtitleAera.top, tfw->xtitle, tfw->xtitle_Length, tfw->xytitlefont);

    tfw->draw.pointsize_1 = 9;      // 点的尺寸(点长宽占据的像素点)。
    tfw->draw.pointsize_2 = 9;      // 点的尺寸(点长宽占据的像素点)。
    tfw->draw.pointstyle_1 = 1;     // 点的形状。0 / 1 （实心 / 空心）圆形；2 / 3（实心 / 空心）正方形；4 / 5（实心 / 空心）三角形；
    tfw->draw.pointstyle_2 = 1;     // 点的形状。0 / 1 （实心 / 空心）圆形；2 / 3（实心 / 空心）正方形；4 / 5（实心 / 空心）三角形；

    //绘制图例。 直接在 y1标题，y2标题后面跟这一个自己的位置，绘制图例
    TwoFunction_draw_point(tfw->y1titleAera.right + tfw->draw.pointsize_1, tfw->y1titleAera.top + tfw->y1titleAera.height / 2,
        tfw->draw.pointsize_1, tfw->draw.pointstyle_1, tfw->draw.point_color_1);
    TwoFunction_draw_point(tfw->y2titleAera.left - tfw->draw.pointsize_2, tfw->y2titleAera.top + tfw->y1titleAera.height / 2,
        tfw->draw.pointsize_2, tfw->draw.pointstyle_2, tfw->draw.point_color_2);


    //绘制函数
  //  TwoFunction draw; // (graphic, functionAera, &scalefont, xfont, yfont);
    TwoFunction_init(&tfw->draw, tfw->functionAera, &tfw->scalefont, xfont, yfont);

    tfw->draw.pointsize_1 = 1;      // 点的尺寸(点长宽占据的像素点)。
    tfw->draw.pointsize_2 = 1;      // 点的尺寸(点长宽占据的像素点)。

    // graphics_fill_area(0, 0, tfw->picWidth, tfw->picHeight, tfw->background_color);
    // fill_rect_area(tfw->functionAera, tfw->background_color);

    //先初始化绘图样式。

    if (is_set_min_max == 0) {
        TwoFunction_init_func(&tfw->draw, x1, y1, n1, x2, y2, n2);
    }
    else
    {
        TwoFunction_set_min_max(&tfw->draw, x1, y1, n1, x2, y2, n2, xmin, xmax, y1min, y1max, y2min, y2max);
    }


    TwoFunction_init_yscale(&tfw->draw);
    TwoFunction_init_xscale(&tfw->draw);

    TwoFunction_draw_scale(&tfw->draw, true);


    if (y1 != NULL && x1 != NULL) {
        tfw->draw.x1 = x1;
        tfw->draw.y1 = y1;
        tfw->draw.pointsNumber1 = n1;
        //下面要规范一下点，确保数据都在范围内。不然后面绘图会出错。
        for (int i = 0; i < n1; i++) {
            if (x1[i] < tfw->draw.x_min)x1[i] = tfw->draw.x_min;
            if (x1[i] > tfw->draw.x_max)x1[i] = tfw->draw.x_max;
            if (y1[i] < tfw->draw.y1_min)y1[i] = tfw->draw.y1_min;
            if (y1[i] > tfw->draw.y1_max)y1[i] = tfw->draw.y1_max;
        }
    }
    else
    {
        tfw->draw.x1 = NULL;
        tfw->draw.y1 = NULL;
        tfw->draw.pointsNumber1 = 0;
    }
    if (y2 != NULL && x2 != NULL) {
        tfw->draw.x2 = x2;
        tfw->draw.y2 = y2;
        tfw->draw.pointsNumber2 = n2;
        //下面要规范一下点，确保数据都在范围内。不然后面绘图会出错。
        for (int i = 0; i < n2; i++) {
            if (x2[i] < tfw->draw.x_min)x2[i] = tfw->draw.x_min;
            if (x2[i] > tfw->draw.x_max)x2[i] = tfw->draw.x_max;
            if (y2[i] < tfw->draw.y2_min)y2[i] = tfw->draw.y2_min;
            if (y2[i] > tfw->draw.y2_max)y2[i] = tfw->draw.y2_max;
        }
    }
    else
    {
        tfw->draw.x2 = NULL;
        tfw->draw.y2 = NULL;
        tfw->draw.pointsNumber2 = 0;
    }
    TwoFunction_draw_points(&tfw->draw, true, true, NULL, NULL); //选择绘制点的格式



    //draw_rect_area(tfw->titleAera, RGB_red);
    //draw_rect_area(tfw->xtitleAera, RGB_red);
    //draw_rect_area(tfw->y1titleAera, RGB_red);
    //draw_rect_area(tfw->y2titleAera, RGB_red);
    //draw_rect_area(tfw->functionAera, RGB_red);

}




#include<math.h>
//调用draw_title会刷新整个图片。因为分区变化了。

//调用draw_func只刷新函数区。


int test_TwoFunctionPicture()
{
    float x[15]={ 54, 64, 95, 168, 193,200, 264, 295, 368, 383,454, 464, 495, 568, 663 };
    float y2[15]={ 1.35, 1.35, 3.58, 1.24, 5.67,1.35, 1.35, 3.58, 1.24, 5.67,1.35, 1.35, 3.58, 1.24, 5.67 };
    float y1[15]={ 11.35, 11.35, 23.58, 21.24, 25.67,21.35, 121.35, 53.58, 111.24, 115.67,81.35, 91.35, 33.58, 41.24, 25.67 };

    int i = 10;
    TwoFunctionPicture tp;
    TwoFunctionPicture_init(&tp, 0, 0, 700, 450);

    char title[] = "Oscilloscope";          //标题
    char xtitle[] = "xtitle time";          //x轴标题
    char y1title[] = "y1title cm";          //y轴标题
    char y2title[] = "y2title km";          //y轴标题
    TwoFunctionPicture_draw_title(&tp, title, xtitle, y1title, y2title);

    y1[7] -= 2;
    y2[2] += 2.1;
    x[9] += 2;


    while (i) {
        y1[7] -= 2;
        y2[2] += 2.1;
        x[9] += 2;

        TwoFunctionPicture_draw_func(&tp, x, y1, 10, x, y2, 10, 1, 0, 0, NULL, NULL);

      //  GD_wait_key_input();	// 按任意键继续
        i -= 1;
    }
    GD_wait_key_input();	// 按任意键继续

    return 0;
}
//

#define fundata_len 100  
int test_TwoFunctionPicture_fast()
{
    float x1[fundata_len] = { 0 };
    float x2[fundata_len] = { 0 };
    float y1[fundata_len] = { 0 };
    float y2[fundata_len] = { 0 };

    for (int i = 0; i < fundata_len; i++) {
        x1[i] = i;
        x2[i] = i;
        y1[i] = 3 * sinf(x1[i] / 10);
        y2[i] = 4 * sinf(x2[i] / 30) + 1 * cosf(x2[i] / 40) + 5;
    }


    TwoFunctionPicture tp;
    TwoFunctionPicture_init(&tp, 0, 0, 700, 450);
    //  TwoFunctionPicture_init(&tp, 320, 400);

    char title[] = "Curve Chart";          //标题
    char xtitle[] = "xtitle time";          //x轴标题
    char y1title[] = "y1title cm";          //y轴标题
    char y2title[] = "y2title km";          //y轴标题
    TwoFunctionPicture_draw_title(&tp, title, xtitle, y1title, y2title);
    printfs("  \r\n draw title ");

    TwoFunctionPicture_fast_draw_func(&tp, x1, y1, fundata_len, x2, y2, fundata_len, 0, 0,
        0,
        -10, 50,
        -2, 2,
        -6, 6
    );
    GD_wait_key_input();	// 按任意键继续
    printfs("  \r\n draw function ");

    int i = 500000;
    while (i)
    {
        i--;
        float nx, ny1, ny2;
     //   int L = fundata_len * 2;
       // nx = i % L - fundata_len / 2;
        nx = i % (fundata_len);

    //    y1[i] = 3 * sinf(x1[i] / 10);
   //     y2[i] = 4 * sinf(x2[i] / 30) + 1 * cosf(x2[i] / 40) + 5;

        ny1 = 2 * sinf((float)i / 10);
        ny2 = 3 * sinf((float)i / 10) + 5 + 1 * cosf((float)i / 40);


        TwoFunction_replace_point(&tp.draw, i % fundata_len, nx, ny1, true);
        TwoFunction_replace_point(&tp.draw, i % fundata_len, nx, ny2, false);
        if (i % (500000 / 5) == 0) {
            GD_wait_key_input();	// 按任意键继续
            printfs("  \r\n draw function   i ");

        }
    }



    GD_wait_key_input();	// 按任意键继续

    return 0;
}
//




